         lst   off

******************************************************************************
*                                                                            *
* CD Remote CDA  ------------------------------------  v1.2 - June 5th, 1990 *
* by Eric C. Mueller, 2760 Roundtop Dr., Col. Springs, CO 80918 719-548-8295 *
*                                                                            *
* >> Use apple-6 to assemble, link, and save the CDA file to disk            *
*                                                                            *
******************************************************************************

         xc               ;allow 65c02 opcodes
         xc               ;allow 65c816 opcodes
         mx    %00        ;full 16 bit code
         cas   in         ;case insensitive
         rel              ;relocatable
         typ   cda        ;filetype = CDA
         dsk   cda.l      ;object file is cda.l
         use   cda.macs   ;use this macro file

*=============================================================================

         do    0          ;turn off assembly for macro defintions
dl       mac              ;define long - same as ADRL
         adrl  ]1
         <<<
         fin              ;turn assembly back on

*=============================================================================
* CDA header

         str   'CD Remote v1.2' ;title
         adrl  StartUp
         adrl  ShutDown

*=============================================================================
* Equates

DInfo    equ   $202C      ;GS/OS calls
DStatus  equ   $202D
DControl equ   $202E

ResetDevice equ $0000     ;generic SCSI call

ReadTOC  equ   $80c1      ;SCSI CD ROM-specific calls
ReadQSubcode equ $80c2

AudioSearch equ $80c8
AudioPlay equ  $80c9
AudioPause equ $80ca
AudioStop equ  $80cb
AudioStatus equ $80cc
AudioScan equ  $80cd

GSOS     equ   $e100a8    ;GS/OS entry point
OS_Kind  equ   $e100bc    ;boolean: is GS/OS the current OS?

         dum   1          ;set up dummy equates for direct page
dpage                     ;start of direct page

temp     dl    0          ;temp variable
GDSstatus dw   0          ;result of GetDeviceStatus cal
maxTrack dw    0          ;max track available on this disc
pauseFlag dw   0          ;flag: is disc currently in pause?
suTT     dw    0          ;flag: did we start up the text tools?
newDiscFlag dw 0          ;boolean: new disc inserted?
endTicks dl    0          ;tick count (for waiting one second)
iANDmsk  dw    0          ;input text device AND mask
iORmsk   dw    0          ;input text device OR mask
oANDmsk  dw    0          ;output text device AND mask
oORmsk   dw    0          ;output text device OR mask
iDevType dw    0          ;input text device type
iPtrOrSlot dw  0          ;input text device slot (or ptr)
oDevType dw    0          ;output text device type
oPtrOrSlot dw  0          ;output text device slot (or ptr)

dend                      ;end of direct page
         dend             ;end of dummy equates

*=============================================================================
* Program

StartUp
         phb              ;save old data bank register

         phk              ;set data bank to pgm. bank
         plb

         tdc              ;save old direct page ptr
         sta   oldDP

         tsc
         sec              ;allocate direct page space
         sbc   #dend-dpage
         tcs              ;set stack and dpage
         tcd

         jsr   Start      ;get the appropriate tools ready

         shortacc         ;short accumulator
         ldal  OS_Kind    ;check OS byte - can't make GS/OS calls from P8!
         longacc
         beq   p8         ;in P8: sorry, we're outta here...

         jsr   Main       ;do the main loop

end
         lda   suTT       ;did we start up the text tools?
         beq   :no        ;no (see below)
         _TextShutDown    ;yes, so get rid of them
         bra   :cont      ;and continue

:no                       ;no, we just used the text tools, so we have to...
         jsr   RestoreTDevs ;...restore the text devices to what they were

:cont    tsc              ;fix up the stack (get rid of our dpage)
         clc
         adc   #dend-dpage
         tcs
         lda   oldDP      ;restore old DP
         tcd

         plb              ;restore old data bank register

ShutDown
         rtl              ;and leave

p8
         ~WriteCString #:proDOS
         jsr   getKey
         bra   end

:proDOS  asc   0d0d0d'Sorry - this CDA requires GS/OS to operate. '00

*=============================================================================
* Main loop

Main
         stz   newDiscFlag
         ~WriteCString #Title ;print title info
         jsr   FindCDRom  ;find the CD-ROM drive
         bcs   :exit      ;exit if none found

:newDisc
         jsr   NewDisc    ;set up for new disc

:1
         jsr   GDS        ;get device status
         and   #%1_0000   ;check disc-in-drive bit
         beq   :noDisc    ;none! don't do anything, now

         lda   newDiscFlag ;check the disc-switched flag
         bne   :newDisc   ;there was a new disc inserted! get it

         jsr   ZeroParamList ;zap old parameter list
         lda   #5         ;return five bytes, please
         sta   DSrequest
         lda   #ReadQSubcode ;find out the current Q subcode info
         jsr   DoDStatus

         lda   #0         ;clear out high byte of accum
         shortacc
         lda   buffer+1   ;get track number
         longacc
         sta   TIBCD      ;store track # in BCD
         jsr   BCD2ASCII
         xba
         sta   TrackInd   ;store track number
         shortacc
         lda   buffer+3   ;get minutes value
         longacc
         jsr   BCD2ASCII  ;convert it
         xba
         sta   Minutes
         shortacc
         lda   buffer+4   ;get seconds value
         longacc
         jsr   BCD2ASCII  ;convert it
         xba
         sta   Seconds

         jsr   Events     ;do our li'l event loop
         bcc   :1         ;quit not picked, keep going

:exit
         rts              ;we're outta here

:noDisc
         ~WriteCString #:discGone
         jsr   getKey
         cmp   #$001b     ;ESC pressed?
         beq   :exit      ;yes - leave now
         jsr   GDS        ;no - get status again...
         bra   :1         ;...and work with it

:discGone asc  0d0d'Please insert a disc and press return, or ESC to exit. '00

Title    asc   'CD ROM REMOTE v1.2, by Eric C. Mueller'0d
         asc   'See develop #3. Copyright, 1990.'0d0d00

* get device status - quick 'n dirty

GDS                       ;
         jsr   ZeroParamList ;zap old parameter list
         lda   #$0002     ;get just the status word (two bytes)
         sta   DSrequest
         lda   #$0000     ;GetDeviceStatus (not device-specific)
         sta   DScode     ;store control code
         jsl   GSOS
         dw    DStatus    ;make GS/OS DStatus call
         adrl  statParm
         lda   statusList ;get status word
         sta   GDSstatus  ;hold status here
         pha
         and   #1         ;check disc-switched bit
         ora   newDiscFlag ;keep old flag, if set
         sta   newDiscFlag ;save status
         pla
         stz   statusList ;(zero parm table for CD-ROM audio calls)
         rts

*=============================================================================
* Display prompt, get key press, handle it, return

Events
         ~WriteCString #prompt ;print the prompt
:0       jsr   getKey     ;get a keypress

         cmp   #$0060     ;is it lowercase?
         blt   :1         ;no
         and   #$00df     ;yes - convert to uppercase
:1

         ldy   #0         ;start at the top of the table
:2       cmp   commands,y ;is this the key pressed?
         beq   :match     ;yes!
         iny              ;no - move past key
         iny
         iny              ;and past address
         iny
         cpy   #endcommands-commands ;at the end of the table?
         bne   :2         ;no - keep looking
         beq   :0         ;yes - ignore invalid keypress

:match                    ;we have a match...
         iny              ;move to address
         iny
         tyx
         jsr   (commands,x) ;call the handler

         rts              ;and return to main loop

commands                  ;table of command keys and addresses for handlers
         dw    'P',Play
         dw    'S',Stop
         dw    'Q',Quit
         dw    ' ',Pause
         dw    '!',Status
         dw    'Z',Reset
         dw    $1b,Quit   ;escape key
         dw    $a,Forward ;down arrow
         dw    $b,Backward ;up arrow
         dw    $15,SrchFwd ;right arrow
         dw    $8,SrchBkd ;left arrow
         dw    '?',Help
         dw    '/',Help
endcommands equ *

prompt
         asc   0d'['
TrackInd asc   '01] '     ;track number indicator
Minutes  asc   '00:'
Seconds  asc   '00 - Enter command or "?" for help: '00

*=============================================================================
* set up for new disc (call on disc-switch events)

NewDisc
         jsr   GDS        ;get device status and newDiscFlag (one last time!)
         ~WriteCString #:nd
         stz   newDiscFlag
         stz   pauseFlag
         lda   #'01'      ;start track indicator on track 1
         sta   TrackInd
         lda   #$0001
         sta   TIBCD      ;store BCD value of track indicator
         shortacc
         lda   #$00
         sta   statusData+5 ;get a type 0 TOC
         longacc
         lda   #$0002     ;get two bytes back
         sta   DSrequest
         lda   #ReadTOC   ;make this call
         jsr   DoDStatus
         shortacc
         lda   buffer+1   ;get last track
         longacc
         jsr   BCD2Hex    ;convert to hex
:noDisc  sta   maxTrack   ;save max track available
         rts              ;and leave

:nd      asc   0d0d'(new disc)'0d00

*-----------------------------------------------------------------------------
* play track CD

Play
         ~WriteCString #playmsg

Play1
         jsr   ZeroParamList ;zap old parameter list
         shortacc
         lda   TIBCD      ;get track (in BCD)
         sta   statusData+2 ;store it in parm list
         lda   #$80       ;we want a type 2 table of contents
         sta   statusData+5
         longacc
         lda   #$0005     ;get five bytes back
         sta   DSRequest
         lda   #ReadTOC   ;find out info about this track
         jsr   DoDStatus
         lda   buffer
         and   #%00000000_0000_1101 ;check out control field
         cmp   #%00000000_0000_0100 ;is this a data track?
         beq   :data      ;yes!

         jsr   ZeroParamList
         shortacc
         lda   maxTrack   ;stop track = last available
                          ;to play only one track, use "lda TIBCD" instead
         sta   controlData+5
         lda   #$80       ;type 2: we're specifying a track number
         sta   controlData+6
         longacc

         lda   #AudioStop
         jsr   DoDControl

         jsr   ZeroParamList ;zap old parameter list
         shortacc
         lda   #%00000000_0000_1001 ;play mode (stereo)
         sta   controlData+3
         lda   TIBCD      ;get track ind. value (in BCD)
         sta   controlData+7 ;store track number
         lda   #$80       ;type 2: we're specifying a track number
         sta   controlData+8
         longacc
         lda   #AudioPlay
         jsr   DoDControl
         stz   pauseFlag  ;clear pause flag
:exit    clc
         rts

:data    ~WriteCString #:datatrack
         bra   :exit

:datatrack asc |          - CAN'T PLAY; data track|00
playmsg  asc   'Play'00

*-----------------------------------------------------------------------------
* get status of drive

Status
         ~WriteCString #:stat

         jsr   ZeroParamList ;zap old parameter list

         lda   #$0006     ;get six bytes from AudioStatus
         sta   DSrequest
         lda   #AudioStatus ;make this call
         jsr   DoDStatus
         shortacc
         lda   buffer     ;get audio status
         longacc
         cmp   #5+1
         bge   :bad
         asl              ;*2 so offset into table is correct
         tay
         lda   #^:msgPtrs ;get current bank
         pha              ;push high word
         lda   :msgPtrs,y ;push low word
         pha
         _WriteCString    ;print string
         clc
         rts

:bad     ~WriteCString #:unk
         clc
         rts

:stat    asc   'Status'0d0d00
:unk     asc   'Unknown audio status returned'0d00
:msgPtrs
         dw    :nowPlay   ;$00
         dw    :pause     ;$01
         dw    :muting    ;$02
         dw    :playComp  ;$03
         dw    :errPlay   ;$04
         dw    :noPlay    ;$05

:nowPlay asc   'AudioPlay operation in progress'0d00
:pause   asc   'Pause operation in progress'0d00
:muting  asc   'Muting On operation in progress'0d00
:playComp asc  'AudioPlay completion status'0d00
:errPlay asc   'Error occurred during AudioPlay operation'0d00
:noPlay  asc   'AudioPlay operation not requested'0d00

*-----------------------------------------------------------------------------
* pause/resume playback

Pause
         lda   #1         ;flip pauseFlag
         sec
         sbc   pauseFlag
         sta   pauseFlag  ;what was the old status?
         beq   :resume    ;...paused! so, resume
         ~WriteCString #:pause
         lda   #$10       ;hold pause
         bra   :1
:resume
         ~WriteCString #:res
         lda   #$00       ;release pause
:1       shortacc
         sta   controlData+2
         longacc
         lda   #AudioPause
         jsr   DoDControl ;do it
         clc
         rts

:pause   asc   'Pause'00
:res     asc   'Resume'00

*-----------------------------------------------------------------------------
* stop audio playback

Stop
         ~WriteCString #:stop
         jsr   ZeroParamList ;zap old parameter list

         shortacc
         lda   #0         ;stop on track zero (stop now)
         sta   controlData+5
         lda   #$80       ;type 2: we're specifying a track number
         sta   controlData+6
         longacc

         lda   #AudioStop
         jsr   DoDControl

         lda   #1
         sta   pauseFlag  ;set pause flag (allow resume)

         clc
         rts

:stop    asc   'Stop'00

*-----------------------------------------------------------------------------
* reset the drive

Reset                     ;
         ~WriteCString #:reset
         jsr   ZeroParamList ;zap old parameter list
         lda   #ResetDevice
         jsr   DoDControl
         lda   #'01'      ;start track indicator on track 1
         sta   TrackInd
         lda   #$0001
         sta   TIBCD      ;store BCD value of track indicator
         jsr   Play1      ;start play on track 1, now
         rts

:reset   asc   'Reset'00

*-----------------------------------------------------------------------------
* search track

SrchFwd
         ~WriteCString #ffwd
         lda   #$00       ;$00 = fast forward
         bra   x1
SrchBkd
         ~WriteCString #frwd
         lda   #$40       ;$40 = fast rewind

x1       shortacc
         pha              ;hold scan type
         longacc

         jsr   ZeroParamList ;zap old parameter list
         lda   #8         ;return eight bytes, please
         sta   DSrequest
         lda   #ReadQSubcode ;find out the current Q subcode info
         jsr   DoDStatus

         jsr   ZeroParamList ;zap old parameter list

         shortacc
         lda   buffer+6   ;get abs. minutes from ReadQSubcode call
         sta   controlData+5 ;save it as start address for scan
         lda   buffer+7   ;get abs. seconds
         sta   controlData+6
         lda   buffer+8   ;get abs. frames
         sta   controlData+7

         pla              ;get scan type back
         sta   controlData+2

         lda   #$40       ;address type 1 = abs. mins, secs, frames
         sta   statusData+8
         longacc

         lda   #AudioScan
         jsr   DoDControl ;do it

         clc
         rts

frwd     asc   'Fast Rewind'00
ffwd     asc   'Fast Forward'00

*-----------------------------------------------------------------------------
* zero out parameter table before filling it up

ZeroParamList
         lda   #0
         ldy   #10        ;zero out parameter list
:1       sta   controlData,y
         sta   statusData,y
         dey
         dey
         bpl   :1
         rts

*-----------------------------------------------------------------------------
* make a DControl call - enter with control code in accumulator

DoDControl
         sta   DCcode     ;store control code
         shortacc
         sta   controlData ;store it in start of the parameter list
         longacc

         jsl   GSOS
         dw    DControl   ;make GS/OS DControl call
         adrl  :devParm

         jsr   GDS        ;get device status & set new disc flag, if necessary

         rts              ;and return with the call made

:devParm dw    5          ;parm list for the DControl call
DCdevNum dw    0          ;fill in device number here
DCcode   dw    0          ;control code
         adrl  controlList ;pointer to buffer
         dl    0          ;requestCount - unused
         dl    0          ;transferCount

controlList dw 0          ;reserved
controlData ds 12         ;12 bytes of data
         adrl  buffer     ;pointer to buffer
buffer   ds    20

*-----------------------------------------------------------------------------
* make a DStatus call - enter with status code in accumulator

DoDStatus
         sta   DScode     ;store control code
         shortacc
         sta   statusData ;store it in start of the parameter list
         longacc

         jsl   GSOS
         dw    DStatus    ;make GS/OS DStatus call
         adrl  statParm

         jsr   GDS        ;get device status & set new disc flag, if necessary

         rts              ;and return with the call made

statParm dw    5          ;parm list for the DStatus call
DSdevNum dw    0          ;fill in device number here
DScode   dw    0          ;status code
         adrl  statusList ;pointer to buffer
DSrequest dl   0          ;requestCount
         dl    0          ;transferCount

statusList dw  0          ;reserved
statusData ds  12         ;12 bytes of data
         adrl  buffer     ;pointer to buffer

*-----------------------------------------------------------------------------
* move track indicator forward

Forward
         ~WriteCString #:for

         jsr   GetTrackIndVal ;get val. of track indicator (not BCD)
         cmp   maxTrack   ;are we on the last track of the disc?
         blt   :no        ;not yet!
         lda   #0         ;yes - wrap back to one
:no      inc              ;move it up one
         jsr   SetTrackIndVal ;set track indicator value
         jsr   Play1      ;send the AudioPlay command
         jsr   WaitOneSec ;and wait one second
         clc
         rts

:for     asc   'Forward'00

*-----------------------------------------------------------------------------
* move track indicator back

Backward
         ~WriteCString #:back
         jsr   GetTrackIndVal ;get val. of track indicator (not BCD)
         cmp   #1         ;are we on the first track?
         beq   :first
         dec              ;no - move back one track
         cmp   maxTrack   ;larger than largest track?
         bge   :first     ;yes - reset it to last track
         bra   :go
:first   lda   maxTrack   ;yes - wrap around to last track
:go      jsr   SetTrackIndVal ;set new track indicator value
         jsr   Play1      ;send the AudioPlay command
         jsr   WaitOneSec ;and wait one second
         clc
         rts

:back    asc   'Backward'00

*-----------------------------------------------------------------------------
* quit

Quit
         sec              ;set carry to indicate that we want to leave
         rts

*-----------------------------------------------------------------------------
* get help

Help
         ~WriteCString #helpInfo
         clc
         rts

helpInfo
         asc   'Help'0d   ;print command
         asc   0d'P = Play'
         asc   0d'S = Stop'
         asc   0d'! = Audio status'
         asc   0d'Z = Zap (reset) drive'
         asc   0d'? = This information'
         asc   0d'Q = Quit'
         asc   0d'Space bar to pause and resume playback.'
         asc   0d'Up and down arrow keys to change track indicator.'
         asc   0d'Left and right arrow keys to do inter-track search'
         hex   0d00

*-----------------------------------------------------------------------------
* wait one second

WaitOneSec                ;this is used after issuing an AudioPlay call, and
                          ;before the following ReadQSubcode. Occasionally,
                          ;the drive can't synchronize the results of the
                          ;DStatus with the actual current Q Subcode. This
                          ;means that you may go from playing track one to
                          ;track two, and while the disc is seeking on (and
                          ;playing) track 2, 00:00, the ReadQSubcode call will
                          ;return track 1, and the last second of track one
                          ;(for example, 02:58, if track one is that long).

                          ;Waiting for one second allows the drive to get it's
                          ;values straight.

         ~GetTick         ;get the starting tick count

         pla              ;get low word of starting tick count
         clc
         adc   #60        ;wait for 60 ticks (one second)
         sta   endTicks
         pla              ;get high word
         adc   #0         ;...add zero to handle any carry
         sta   endTicks+2

:loop                     ;now, wait until we're
         ~GetTick         ;get current tick count

         pla              ;get value
         plx
         cmp   endTicks   ;does low word match?
         bne   :loop      ;no, keep waiting
         cpx   endTicks+2 ;yes - how about high word?
         bne   :loop      ;no, keep waiting

         rts              ;yes; a second has passed. leave.

*-----------------------------------------------------------------------------
* get track indicator value (returns value in hex)

GetTrackIndVal
         lda   TrackInd   ;get track indicator ($3233)
         xba              ;flip it ($3332)
         and   #$0f0f     ;get rid of ASCII parts ($0302)
         pha              ;hold that for a moment ($0302)
         and   #$00ff     ;zap high word ($0002)
         sta   temp       ;store it ($0002)
         pla              ;get old value back ($0302)
         xba              ;flip it ($0203)
         shortacc
         asl              ;promote low nibble ($03 -> $30)
         asl
         asl
         asl
         longacc
         and   #$00ff     ;get rid of residue in high word
         ora   temp       ;now we should have $0032

         sta   TIBCD      ;store BCD value of track indicator

* now change the BCD value into hex
         jsr   BCD2Hex
         rts

*-----------------------------------------------------------------------------
* convert BCD value into hex value

BCD2Hex
         ldx   #0         ;start with zero
         sed              ;turn decimal mode on
:1       inx
         sec              ;bump it down one
         sbc   #1
         bne   :1         ;keep going!
         cld

         txa              ;returns with hex value in accum
         rts

*-----------------------------------------------------------------------------
* set track indicator value (enter with hex value - exits with BCD value)

SetTrackIndVal
                          ;first, change value into BCD
         tax
         lda   #0
         sed              ;turn decimal mode on
:1       clc              ;bump it down one
         adc   #1
         dex
         bne   :1         ;keep going!
         cld

         sta   TIBCD      ;store BCD value of track indicator

         rts

BCD2ASCII
         pha              ;hold original ($0012)
         and   #$000f     ;isolate low byte ($0002)
         ora   #$0030     ;make it ASCII ($0032)
         sta   temp       ;hold it for now ($0032)
         pla              ;get original back ($0012)
         and   #$00f0     ;isolate the high nibble of the low byte ($0010)
         asl              ;promote it to low nibble of high byte ($0100)
         asl
         asl
         asl
         ora   #$3000     ;make it ASCII ($3100)
         ora   temp       ;add on low byte ($3132 = '12')
         rts              ;and go with it

*-----------------------------------------------------------------------------
* find the CD-ROM drive

FindCDRom
         lda   CDROMDev   ;have we found it before?
         bne   :leave     ;yes - leave now

:look                     ;start looking for drive
         jsl   GSOS
         dw    DInfo      ;make GS/OS DInfo call
         adrl  :devParm
         bcs   :err       ;leave if error

         lda   devID      ;get device ID
         cmp   #$0007     ;is is a SCSI CD ROM device?
         beq   :found     ;yes - found it

         inc   devNum     ;no - move to next device
         bra   :look      ;and keep looking

:found   lda   devNum
         sta   CDROMDev
         sta   DCdevNum   ;store device number for all control calls
         sta   DSdevNum   ;store device number for all status calls
:leave   clc              ;found it
         rts

:none    ~WriteCString #:noCDRom
:1       jsr   getKey
         sec              ;none found!
         rts

:err     cmp   #$11       ;error $11 - invalid device number?
         beq   :none      ;yes - no CD-ROM drive found!
         ~WriteCString #:error ;no - some other weird error
         bra   :1

:error   asc   0d'GS/OS error on DInfo call. Press any key to quit. '0700
:noCDRom asc   0d'No CD-ROM drive found. Press any key to quit. '0700

:devParm dw    8          ;8 parameters
devNum   dw    1          ;device number - start with one
         adrl  nameBuffer ;pointer to buffer for device name
         dw    0          ;characteristics
         dl    0          ;totalBlocks
         dw    0          ;slotNum
         dw    0          ;unitNum
         dw    0          ;version
devID    dw    0          ;device ID: $0007 = SCSI CD ROM

nameBuffer dw  31         ;max length
         ds    33         ;storage for device name

*-----------------------------------------------------------------------------
* get a keypress, returned in the accum

getKey
         ~ReadChar #0     ;don't echo it
         pla
         and   #$007f     ;isolate low byte
         rts

*-----------------------------------------------------------------------------
* start up appropriate tools

Start                     ;get the right tools up
         stz   suTT       ;zap flag: assume they're already up
         ~TextStatus      ;get the status of the text tools
         pla
         bcs   :startEm   ;start them!
         bne   :alreadyUp ;if they're already up, don't re-start them

:startEm _TextStartUp     ;(unnecessary if we came from the CDA menu)
         inc   suTT       ;set flag so we know to shut them down, too
         bra   :cont

:alreadyUp                ;they're already up, so....
         ~GetInputDevice  ;get the current input device
         PullLong iPtrOrSlot
         PullWord iDevType
         ~GetInGlobals    ;get current input device globals
         PullWord iORmsk
         PullWord iANDmsk
         ~GetOutputDevice ;get the current output device
         PullLong oPtrOrSlot
         PullWord oDevType
         ~GetOutGlobals   ;get the current output device globals
         PullWord oORmsk
         PullWord oANDmsk

:cont
         ~SetInputDevice #$0000;#$00000003 ;basic driver - slot 3
         ~SetOutputDevice #$0000;#$00000003 ;same as above
         ~SetInGlobals #$00ff;#$0080 ;AND mask, OR mask
         ~SetOutGlobals #$00ff;#$0080 ;same as above
         bra   InitTDevs  ;init the text devices and leave

RestoreTDevs              ;restore the text devices to what they were before
         ~SetInGlobals iANDmsk;iORmsk ;restore AND mask and OR mask
         ~SetOutGlobals oANDmsk;oORmsk ;same as above
         ~SetInputDevice iDevType;iPtrOrSlot ;restore driver type and location
         ~SetOutputDevice oDevType;oPtrOrSlot ;same as above
                          ;and leave by re-initializing the devices

InitTDevs
         ~InitTextDev #$0000 ;get input device ready
         ~InitTextDev #$0001 ;get output device ready
         rts

******************************************************************************
* data area

TIBCD    dw    0          ;track indicator (BCD value)
CDROMDev dw    0          ;CD-ROM device number

oldDP    dw    0          ;old direct-page register value
